/*
 * This file is part of FinVis.
 *
 * FinVis is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * FinVis is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with FinVis.  If not, see <http://www.gnu.org/licenses/>
 *
 * @author Stephen Rudolph
 */

#include <QBoxLayout>
#include <QMessageBox>
#include <QStandardItemModel>
#include <QTableView>
#include <QPushButton>

#include <map>
#include <vector>

#include "Common.h"
#include "FinList.h"
#include "FinPortfolio.h"

extern FinPortfolio scenarioPortfolio;
extern std::vector<InvestmentOption> investmentOptionVector;
extern double **covarianceArray;

using namespace std;

/**
 * Constructor
 */
FinList::FinList(QWidget *parent, Qt::WindowFlags flags)
        : QDockWidget(parent, flags)
        , m_widgetSize(QSize(MAIN_VIEW_WIDTH, INVESTMENT_LIST_HEIGHT))
        , m_investmentVectorView(new QTableView(this))
        , m_model(new QStandardItemModel(0, 5, this))
        , m_addInvestment(new QPushButton("+", this))
        , m_removeInvestment(new QPushButton("-", this))
        , m_listWidget(new QWidget)
        , m_loading(false)
{
    //Intialize view components
    this->setWindowTitle(tr("Investment List"));

    m_investmentVectorView->setSelectionBehavior(QAbstractItemView::SelectRows);
    m_investmentVectorView->setSelectionMode(
            QAbstractItemView::SingleSelection);
    m_investmentVectorView->setSortingEnabled(true);

    m_model->setHeaderData(0, Qt::Horizontal, "id");
    m_model->setHeaderData(1, Qt::Horizontal, "Principal ($)");
    //model->setHeaderData(2, Qt::Horizontal, "Year");
    m_model->setHeaderData(2, Qt::Horizontal, "Investment Type");
    //model->setHeaderData(4, Qt::Horizontal, "Length");
    m_model->setHeaderData(3, Qt::Horizontal,
                           QString::fromUtf8("Stdandard Deviation (σ)"));
    m_model->setHeaderData(4, Qt::Horizontal, "Interest (%)");

    m_investmentVectorView->setModel(m_model);
    m_investmentVectorView->setColumnHidden(0, true);
    m_investmentVectorView->sortByColumn(0, Qt::AscendingOrder);
    m_investmentVectorView->resizeColumnsToContents();
    m_investmentVectorView->setEditTriggers(QAbstractItemView::NoEditTriggers);

    m_addInvestment->setMinimumSize(50, 30);
    m_addInvestment->setEnabled(false);

    m_removeInvestment->setMinimumSize(50, 30);
    m_removeInvestment->setEnabled(false);

    QHBoxLayout *buttonLayout = new QHBoxLayout;
    buttonLayout->addStretch();
    buttonLayout->addWidget(m_addInvestment);
    buttonLayout->addWidget(m_removeInvestment);
    buttonLayout->addStretch();

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(m_investmentVectorView);
    mainLayout->addLayout(buttonLayout);

    m_listWidget->setLayout(mainLayout);
    setWidget(m_listWidget);

    m_widgetSize.setHeight(m_listWidget->sizeHint().height());

    //Connections
    connect(m_investmentVectorView, SIGNAL(clicked(const QModelIndex &)),
            this, SLOT(currentRowChanged(const QModelIndex &)));
    connect(m_addInvestment, SIGNAL(pressed()),
            this, SIGNAL(addAndSelectInvestment()));
    connect(m_removeInvestment, SIGNAL(pressed()),
            this, SIGNAL(removeSelectedInvestment()));

    // In case there is existing portfolio data loaded, grab it.
    this->portfolioDataChanged();
}

QSize FinList::minimumSizeHint() const
{
    return QSize(MINIMUM_SIZE, MINIMUM_SIZE);
}

QSize FinList::sizeHint() const
{
    return m_widgetSize;
}

/**
 * Enable add/remove buttons
 */
void FinList::enableButtons()
{
    m_addInvestment->setEnabled(true);
    m_removeInvestment->setEnabled(true);
}

/**
 * Disable add/remove buttons
 */
void FinList::disableButtons()
{
    m_addInvestment->setEnabled(false);
    m_removeInvestment->setEnabled(false);
}

/**
 * Refresh the list in response to the portfolio changing
 */
void FinList::portfolioDataChanged()
{
    m_loading = true;

    m_model->removeRows(0, m_model->rowCount());
    m_model->setRowCount(scenarioPortfolio.investmentCount());

    map<unsigned int, FinInvestment> investments =
            scenarioPortfolio.investments();
    unsigned int index = 0;
    map<unsigned int, FinInvestment>::iterator investmentIterator;
    for(investmentIterator = investments.begin();
        investmentIterator != investments.end();
        ++investmentIterator)
    {
        int id = investmentIterator->first;
        m_model->setData(m_model->index(index, 0, QModelIndex()),
                         QString::number(id));
        m_model->setData(m_model->index(index, 1, QModelIndex()),
                         tr("$") + QString::number(
                                 scenarioPortfolio.principalForInvestment(id)));
        //m_model->setData(m_model->index(index, 2, QModelIndex()), 
        //                  QString::number(
        //                  scenarioPortfolio.startYearForInvestment(index)));
        
        InvestmentOption option = investmentOptionVector.at(
                scenarioPortfolio.investmentOptionVectorIndexForInvestment(id));
        m_model->setData(m_model->index(index, 2, QModelIndex()),
                         tr(option.name));
        //m_model->setData(m_model->index(index, 4, QModelIndex()),
        //  QString::number(scenarioPortfolio.durationForInvestment(index)));
        m_model->setData(m_model->index(index, 3, QModelIndex()),
                         QString::number(option.standardDeviation, 'g', 3));
        m_model->setData(m_model->index(index, 4, QModelIndex()),
                         QString::number(
                                 option.annualPercentageReturn, 'g', 3));

        m_investmentVectorView->setModel(m_model);
        index++;
    }

    for(int i = 0; i < m_model->rowCount(); i++)
    {
        if(m_model->item(i, 0)->text().toInt() ==
           scenarioPortfolio.selectedID())
        {
            m_investmentVectorView->selectRow(i);
            break;
        }
    }

    m_investmentVectorView->reset();
    m_investmentVectorView->resizeColumnsToContents();
    m_investmentVectorView->sortByColumn(0, Qt::AscendingOrder);

    m_loading = false;
}

/**
 * Highlight the newly selected investment
 */
void FinList::selectionChanged()
{
    for(int i = 0; i < m_model->rowCount(); i++)
    {
        if(m_model->item(i, 0)->text().toInt() ==
           scenarioPortfolio.selectedID())
            m_investmentVectorView->selectRow(i);
    }
}

/**
 * If the row was changed by the user, select the corresponding investment
 */
void FinList::currentRowChanged(const QModelIndex &i)
{
    if(!m_loading
       && i.isValid()
       && m_model->item(i.row())->text().toUInt() !=
            scenarioPortfolio.selectedID())
        emit selectionChanged(m_model->item(i.row(), 0)->text().toUInt());
}

